﻿using System;
using System.Threading;
using GammaJul.LgLcd;
using VosSoft.ZuneLcd.Api;

namespace VosSoft.ZuneLcd.Monochrome
{
    internal class Program
    {
        private static readonly AutoResetEvent waitAre = new AutoResetEvent(false);
        private static volatile bool deviceArrived = false;
        private static volatile bool mustExit = false;

        private static MainPage mainPage;
        private static ZuneLcdApi zune;

        [MTAThread]
        internal static void Main()
        {
#if DEBUG
            Debug("Zune LCD is starting up...");
#endif
            LcdApplet applet = null;

            applet = new LcdApplet("Zune LCD (Monochrome)", LcdAppletCapabilities.Monochrome, false);

            applet.DeviceArrival += new EventHandler<LcdDeviceTypeEventArgs>(applet_DeviceArrival);
            applet.DeviceRemoval += new EventHandler<LcdDeviceTypeEventArgs>(applet_DeviceRemoval);
            applet.IsEnabledChanged += new EventHandler(applet_IsEnabledChanged);
            applet.ConnectionDisrupted += new EventHandler(applet_ConnectionDisrupted);

            applet.Connect();
#if DEBUG
            Debug("Wait until a monochrome device arrives...");
#endif
            waitAre.WaitOne();

            LcdDeviceMonochrome device = null;
            TimeSpan waitTime = TimeSpan.FromSeconds(1.0 / 30);

            do
            {
                if (deviceArrived)
                {
                    if (device == null)
                    {
                        device = (LcdDeviceMonochrome)applet.OpenDeviceByType(LcdDeviceType.Monochrome);
                        device.SoftButtonsChanged += new EventHandler<LcdSoftButtonsEventArgs>(device_SoftButtonsChanged);

                        mainPage = new MainPage(device);

                        device.Pages.Add(mainPage);
                        device.CurrentPage = mainPage;

                        zune = new ZuneLcdApi();

                        zune.Starting += new EventHandler(zune_Starting);
                        zune.Ready += new EventHandler(zune_Ready);
                        zune.Closed += new EventHandler(zune_Closed);

                        zune.TrackChanged += new EventHandler(zune_TrackChanged);
                        zune.TrackPositionChanged += new EventHandler(zune_TrackPositionChanged);
                        zune.TrackStatusChanged += new EventHandler(zune_TrackStatusChanged);
                        zune.TrackRatingChanged += new EventHandler(zune_TrackRatingChanged);

                        zune.FastForwardChanged += new EventHandler(zune_FastForwardChanged);
                        zune.VolumeChanged += new EventHandler(zune_VolumeChanged);

                        zune.MuteChanged += new EventHandler(zune_MuteChanged);
                        zune.RepeatChanged += new EventHandler(zune_RepeatChanged);
                        zune.ShuffleChanged += new EventHandler(zune_ShuffleChanged);
                        
                        zune.Launch();
                    }
                    else
                        device.ReOpen();
                    deviceArrived = false;
                }

                if (applet.IsEnabled && device != null && !device.IsDisposed)
                    device.DoUpdateAndDraw();

                Thread.Sleep(waitTime);
            }
            while (!mustExit);

            if (device != null)
            {
                if (mainPage != null)
                    mainPage.Dispose();
                device.Dispose();
            }

            if (applet.IsConnected)
                applet.Disconnect();
            applet.Dispose();
        }

#if DEBUG
        private static void Debug(string msg)
        {
            Console.WriteLine(DateTime.Now.TimeOfDay.ToString() + ": " + msg);
        }
#endif

        private static void applet_DeviceArrival(object sender, LcdDeviceTypeEventArgs e)
        {
#if DEBUG
            Debug("Device arrived: " + e.DeviceType.ToString());
#endif
            if (e.DeviceType == LcdDeviceType.Monochrome)
            {
                deviceArrived = true;
                waitAre.Set();
            }
        }

        private static void applet_DeviceRemoval(object sender, LcdDeviceTypeEventArgs e)
        {
#if DEBUG
            Debug("Device removed: " + e.DeviceType.ToString());
#endif
            waitAre.WaitOne();
        }

        private static void applet_IsEnabledChanged(object sender, EventArgs e)
        {
#if DEBUG
            Debug("Applet IsEnabledChanged: " + ((LcdApplet)sender).IsEnabled.ToString());
#endif
            if (((LcdApplet)sender).IsEnabled)
                waitAre.Set();
            else
                waitAre.WaitOne();
        }

        private static void applet_ConnectionDisrupted(object sender, EventArgs e)
        {
#if DEBUG
            Debug("Applet ConnectionDisrupted!");
#endif
            waitAre.WaitOne();
        }

        private static void device_SoftButtonsChanged(object sender, LcdSoftButtonsEventArgs e)
        {
#if DEBUG
            Debug("Botton pressed: " + e.SoftButtons.ToString());
#endif
            if (!zune.IsReady)
                return;

            switch (e.SoftButtons)
            {
                case LcdSoftButtons.Button0:
                    zune.CurrentTrack.ToggleRating();
                    break;
                case LcdSoftButtons.Button1:
                    zune.ToggleRepeat();
                    break;
                case LcdSoftButtons.Button2:
                    zune.ToggleShuffle();
                    break;
                case LcdSoftButtons.Button3:
                    zune.ToggleMute();
                    break;
            }
        }

        private static void zune_Starting(object sender, EventArgs e)
        {
#if DEBUG
            Debug("Zune is starting up...");
#endif
        }

        private static void zune_Ready(object sender, EventArgs e)
        {
#if DEBUG
            Debug("Zune is ready!");
#endif
            mainPage.Volume.Value = (int)zune.Volume;
            mainPage.SetMute(zune.Muted);
            mainPage.SetRepeat(zune.Repeating);
            mainPage.SetShuffle(zune.Shuffling);
        }

        private static void zune_Closed(object sender, EventArgs e)
        {
#if DEBUG
            Debug("Zune closed!");
#endif
            mustExit = true;
        }

        private static void zune_TrackChanged(object sender, EventArgs e)
        {
#if DEBUG
            Debug("TrackChanged => " + zune.CurrentTrack.ToString());
#endif
            mainPage.Line1.Text = zune.CurrentTrack.Artist;
            mainPage.Line2.Text = zune.CurrentTrack.Title;

            mainPage.Duration.Text = zune.CurrentTrack.DurationFormat;
        }

        private static void zune_TrackPositionChanged(object sender, EventArgs e)
        {
            mainPage.Position.Text = zune.CurrentTrack.PositionFormat;

            int duration = (int)zune.CurrentTrack.Duration.TotalSeconds;
            if (duration > 0)
                mainPage.Progress.Value = (int)zune.CurrentTrack.Position.TotalSeconds * 100 / duration;
            else
                mainPage.Progress.Value = 0;
        }

        private static void zune_TrackStatusChanged(object sender, EventArgs e)
        {
#if DEBUG
            Debug("TrackStatusChanged => " + zune.TrackState.ToString());
#endif
            switch (zune.TrackState)
            {
                case TrackState.Playing:
                    mainPage.SetTrackStateIcon(zune.FastForwarding ? Icons.FastForward : Icons.Play);
                    break;
                case TrackState.Paused:
                    mainPage.SetTrackStateIcon(Icons.Pause);
                    break;
                default:
                    mainPage.SetTrackStateIcon(Icons.Stop);
                    break;
            }
        }

        private static void zune_TrackRatingChanged(object sender, EventArgs e)
        {
#if DEBUG
            Debug("TrackRatingChanged => " + zune.CurrentTrack.Rating.ToString());
#endif
            mainPage.SetTrackRating(zune.CurrentTrack.Rating);
        }

        private static void zune_FastForwardChanged(object sender, EventArgs e)
        {
#if DEBUG
            Debug("FastForwardChanged => " + zune.FastForwarding.ToString());
#endif
            mainPage.SetTrackStateIcon(zune.FastForwarding ? Icons.FastForward : Icons.Play);
        }

        private static void zune_VolumeChanged(object sender, EventArgs e)
        {
#if DEBUG
            Debug("VolumeChanged => " + zune.Volume.ToString());
#endif
            mainPage.Volume.Value = (int)zune.Volume;
        }

        private static void zune_MuteChanged(object sender, EventArgs e)
        {
#if DEBUG
            Debug("MuteChanged => " + zune.Muted.ToString());
#endif
            mainPage.SetMute(zune.Muted);
        }

        private static void zune_RepeatChanged(object sender, EventArgs e)
        {
#if DEBUG
            Debug("RepeatChanged => " + zune.Repeating.ToString());
#endif
            mainPage.SetRepeat(zune.Repeating);
        }

        private static void zune_ShuffleChanged(object sender, EventArgs e)
        {
#if DEBUG
            Debug("ShuffleChanged => " + zune.Shuffling.ToString());
#endif
            mainPage.SetShuffle(zune.Shuffling);
        }
    }
}
